package com.youka.bussiness.common.utils;

import com.youka.bussiness.common.base.BaseException;
import org.apache.commons.lang.StringUtils;
import org.dom4j.*;
import org.tinygroup.parser.filter.PathFilter;
import org.tinygroup.xmlparser.formatter.XmlFormater;
import org.tinygroup.xmlparser.node.XmlNode;
import org.tinygroup.xmlparser.parser.XmlStringParser;

import java.util.*;

/**
 * XMLxml树处理工具类
 */
public class XmlUtil {

    /**
     * xml树转换
     *
     * @param xml
     * @return
     */
    public static XmlNode getXmlNode(String xml) {
        return new XmlStringParser().parse(xml).getRoot();
    }

    /**
     * 获取单节点
     *
     * @param nodePath
     * @param xmlNode
     * @return
     */
    public static String getSingleNode(String nodePath, XmlNode xmlNode) {
        PathFilter<XmlNode> pathFilter = new PathFilter<XmlNode>(xmlNode);
        XmlNode node = pathFilter.findNode(nodePath);
        return node == null ? "" : node.getContent();
    }

    /**
     * 获取多节点
     *
     * @param nodePath
     * @param xmlNode
     * @return
     */
    public static List<XmlNode> getListNode(String nodePath, XmlNode xmlNode) {
        PathFilter<XmlNode> pathFilter = new PathFilter<XmlNode>(xmlNode);
        List<XmlNode> node = pathFilter.findNodeList(nodePath);
        return node;
    }

    /**
     * 替换XML节点值
     *
     * @param resourceXml
     * @param nodePath
     * @param nodeValue
     * @return
     */
    public static String replaceNodeContent(String resourceXml, String nodePath, String nodeValue) {
        XmlNode xmlNode = getXmlNode(resourceXml);
        PathFilter<XmlNode> pathFilter = new PathFilter<XmlNode>(xmlNode);
        XmlNode node = pathFilter.findNode(nodePath);
        node.setContent(nodeValue);
        return node.toString();
    }

    /**
     * 将XML转为Map
     *
     * @param resourceXml 源XML
     * @return
     */
    public static TreeMap<String, Object> xmlToMap(String resourceXml) {

        //返回数据集合
        TreeMap<String, Object> map = new TreeMap<String, Object>();

        //判断源XML是不是为空
        if (StringUtils.isBlank(resourceXml)) {
            return map;
        }

        //使用Dom4j遍历
        try {
            //得到Document对象
            Document document = DocumentHelper.parseText(resourceXml);

            //得到根节点
            Element root = document.getRootElement();

            map = (TreeMap<String, Object>) xmlToMap(root);

        } catch (DocumentException e) {
            throw new BaseException("1001", "将XML转为DOCUMENT对象发生异常");
        }
        return map;
    }

    /**
     * 将XML转为Map
     *
     * @param element
     * @return
     */
    private static Object xmlToMap(Element element) {

        //返回数据Map
        TreeMap<String, Object> map = new TreeMap<String, Object>();

        //节点List结合
        List<Element> elements = element.elements();

        //有多个节点
        if (elements.size() > 0) {
            //多个子节点的话就得考虑list的情况了，比如多个子节点有节点名称相同的
            //构造一个map用来去重

            //创建临时寄存器Map
            Map<String, Element> tempMap = new HashMap<String, Element>();
            for (Element e : elements) {
                tempMap.put(e.getName(), e);
            }

            //遍历寄存器中的Value
            Set<String> keySet = tempMap.keySet();
            for (String key : keySet) {
                Namespace namespace = tempMap.get(key).getNamespace();
                List<Element> elementList = element.elements(new QName(key, namespace));
                //如果同名的数目大于1则表示要构建list，循环递归
                if (elementList.size() > 1) {
                    List<Object> list = new ArrayList<Object>();
                    for (Element ele : elementList) {

                        //递归
                        list.add(xmlToMap(ele));
                    }
                    map.put(key, list);
                } else {
                    //同名的数量不大于1则直接递归去
                    map.put(key, xmlToMap(elementList.get(0)));
                }
            }
        } else {
            map.put(element.getName(), element.getText());
            if (!element.isRootElement()) {
                return element.getText();
            }
        }
        return map;
    }

    /**
     * 将Map转为Xml
     *
     * @param map
     * @return
     */
    public static String mapToXml(SortedMap<String, Object> map) {
        StringBuffer xml = new StringBuffer();
        xml.append("<xml>");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            xml.append("<").append(entry.getKey()).append(">")
                    .append("<![CDATA[").append(entry.getValue()).append("]]>")
                    .append("</").append(entry.getKey()).append(">");
        }
        xml.append("</xml>");
        return xml.toString();
    }

    /**
     * XML格式化
     *
     * @param xml
     * @return
     */
    public static String formatXml(String xml) {
        XmlFormater formater = new XmlFormater();
        StringBuffer xmlStr = new StringBuffer();
        xmlStr.append("<?xml version='1.0' encoding='UTF-8'?>")
                .append(System.getProperty("line.separator"))
                .append(formater.format(new XmlStringParser().parse(xml)));
        return xmlStr.toString();
    }
}